﻿Imports System.Linq.Expressions

Namespace Assets

    Public Class StartsWith
        Implements ICustomExpression

        Public Function ExpressionPointer() As KeyValuePair(Of String, ExpressionFunc) Implements ICustomExpression.ExpressionPointer
            Return New KeyValuePair(Of String, ExpressionFunc)("*", AddressOf StartsWith)
        End Function

        Public Shared Function StartsWith(ByVal left As Expression, ByVal right As Expression) As Expression

            Try
                Dim _methodinfo As Reflection.MethodInfo = GetType(System.String).GetMethod("StartsWith", New Type() {GetType(System.String), GetType(StringComparison)})
                Dim _comparison As Expression = ConstantExpression.Constant(StringComparison.OrdinalIgnoreCase)

                If left.Type Is GetType(System.String) Then
                    'build a method call expression using above property.StartsWith(?)
                    Dim _startswith As MethodCallExpression
                    If right.Type Is GetType(System.String) Then
                        _startswith = Expression.Call(left, _methodinfo, New Expression() {right, _comparison})
                    Else
                        Dim _righttostring As MethodCallExpression = Expression.Call(right, right.Type.GetMethod("ToString", Type.EmptyTypes))
                        _startswith = Expression.Call(left, _methodinfo, New Expression() {_righttostring, _comparison})
                    End If
                    Return BinaryExpression.Equal(_startswith, Expression.Constant(True))
                Else
                    'left and right will need ToString conversion
                    Dim _lefttostring As MethodCallExpression = Expression.Call(left, left.Type.GetMethod("ToString", Type.EmptyTypes))
                    Dim _righttostring As MethodCallExpression = Expression.Call(right, right.Type.GetMethod("ToString", Type.EmptyTypes))
                    Dim _startswith As MethodCallExpression = Expression.Call(_lefttostring, _methodinfo, New Expression() {_righttostring, _comparison})
                    Return BinaryExpression.Equal(_startswith, Expression.Constant(True))
                End If
            Catch ex As InvalidOperationException
                Throw
            End Try
        End Function

    End Class

End Namespace
